package kz.pompei.ifacer.grot.acts;

import kz.pompei.ifacer.util.HandlerList;

public class ActContainer {
  private Act first = null;
  private Act justUsed = null;
  private Act fixed = null;
  public final GrotStorage storage = new GrotStorage();
  
  public final HandlerList updates = new HandlerList();
  
  public ActContainer() {}
  
  public boolean canUndo() {
    return justUsed != null;
  }
  
  public void clean() {
    storage.clean();
    first = justUsed = null;
    fixed = null;
  }
  
  public void fix() {
    fixed = justUsed;
  }
  
  public boolean modified() {
    return fixed != justUsed;
  }
  
  public boolean canRedo() {
    if (justUsed == null) return first != null;
    return justUsed.next != null;
  }
  
  public void addAct(Act act) throws Exception {
    if (act == null) return;
    act.apply(storage);
    
    act.next = act.prev = null;
    if (justUsed == null) {
      justUsed = first = act;
    } else {
      justUsed.next = act;
      act.prev = justUsed;
      justUsed = act;
    }
    if (first == null) {
      first = act;
    }
    
    updates.fire();
  }
  
  public void mergeAct(Act act) throws Exception {
    if (justUsed != null && justUsed.canMerge(act)) {
      justUsed.mergeAndApply(act, storage);
      updates.fire();
      return;
    }
    addAct(act);
  }
  
  public void undo() throws Exception {
    if (justUsed == null) return;
    justUsed.cancel(storage);
    justUsed = justUsed.prev;
    updates.fire();
  }
  
  public void redo() throws Exception {
    if (justUsed == null) {
      if (first == null) return;
      first.apply(storage);
      justUsed = first;
      updates.fire();
      return;
    }
    if (justUsed.next == null) return;
    justUsed.next.apply(storage);
    justUsed = justUsed.next;
    updates.fire();
  }
}
